<?php
declare (strict_types=1);

namespace app\user\logic\user;

use app\admin\logic\system\Config as SystemConfig;
use app\common\command\decrypt\Des;
use app\common\exception\LogicException;
use app\common\helper\util\SnowFlake;
use app\common\logic\Payment as PaymentLogic;
use app\common\logic\Verify;
use app\user\model\user\Encashment;
use app\user\model\user\Income as IncomeModel;
use GuzzleHttp\Client;
use think\facade\Request;
use think\Model;

/**
 * 账户收入接口类
 */
class Income extends IncomeModel
{

    public function userIncome()
    {
        return $this->scope('mid')->value('income') ?: 0;
    }

    public function userIncomeInfo($mid = 0)
    {
        return $this->scope('mid', $mid ?? request()->mid)->findOrEmpty();
    }

    public function userTotalIncome()
    {
        return $this->scope('mid')->value('total_income') ?: 0;
    }

    public function basic(): array
    {
        // 用户收入
        $return['income'] = $this->userIncome();
        // 提现方式
        $return['encashment_way'] = app(PaymentLogic::class)->payway();
        // 充值配置
        $ratio           = SystemConfig::get('income.config', ['ratio' => '1:1']);
        $return['ratio'] = $ratio['ratio'];
        // 余额
        if (in_array('lcnpay', $return['encashment_way'])) {
            $return['balance'] = app(Balance::class)->userBalance();
        }

        return $return;
    }

    /* 收入提现：生成订单 -> 扣除收入 -> 后台审核 -> a、b
     *   a、通过：
     *     修改状态 -> 三方转账 -> 1、2
     *         1、转账成功
     *         2、转账失败 -> 提示错误、修改状态
     *   b、驳回：
     *     修改状态
     */

    /**
     * 收入提现 - 提现到余额
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-05
     */
    public function toBalance($param)
    {
        // 验证数据
        $this->getValidate()->scene('to_balance')->failException()->check($param);
        // 验证提现金额
        $money = $param['money'];
        $mid   = request()->mid;
        $this->checkMoney($money);
        // 提交订单
        $this->startTrans();
        try {
            // 订单
            $create_data = [
                'order_no' => app(SnowFlake::class)->createTX(),
                'mhm_id'   => request()->mhm_id,
                'user_id'  => $mid,
                'money'    => $money,
                'type'     => 0,
                'status'   => 2,
            ];
            $order       = app(Encashment::class)::create($create_data);
            if ($order->isEmpty()) throw new LogicException("申请提现失败");
            // 余额及流水变更
            app(Balance::class)->increaseUserBalance(
                $mid,
                12,
                $money,
                'user_encashment',
                $order->order_no,
                '收入提现到余额：' . $money
            );
            // 扣除收入
            $this->decreaseIncome($money, '收入提现到余额：' . $money);
            $this->commit();
        } catch (LogicException $e) {
            $this->rollback();
            throw new LogicException($e->getMessage());
        }
    }

    /**
     * 收入提现 - 提现到支付宝
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-10
     */
    public function toAlipay($param)
    {
        $device_type = request()->device_type;
        // 验证数据
        $this->getValidate()->scene('to_alipay')->failException()->check($param);
        // 验证提现金额
        $money = $param['money'];
        $this->checkMoney($money);
        // 验证码
        // PC端或用户手机号不是提现账号时需要验证，其他均不验证
        if ($device_type == 'pc' || request()->user->phone != $param['alipay_account']) {
            $code = $param['verify_code'];
            // if ( isset($param['verify_code']) ) {
            $this->checkVerifyCode($code, 'alipay');
            // }
        }

        // 提交订单
        $this->startTrans();
        try {
            // 生成订单
            $create_data = [
                'order_no'         => app(SnowFlake::class)->createTX(),
                'mhm_id'           => request()->mhm_id,
                'user_id'          => request()->mid,
                'money'            => $money,
                'type'             => 2,
                'status'           => 1,
                'alipay_user_name' => $param['alipay_user_name'],
                'alipay_account'   => $param['alipay_account'],
            ];
            $order       = app(Encashment::class)::create($create_data);
            if ($order->isEmpty()) throw new LogicException("申请提现失败");
            // 扣除收入
            $this->decreaseIncome($money, '收入提现到支付宝：' . $money);
            $this->commit();
        } catch (LogicException $e) {
            $this->rollback();
            throw new LogicException($e->getMessage());
        }
    }

    /**
     * 收入提现 - 提现到微信
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-10
     */
    public function toWxpay($param)
    {
        $device_type = request()->device_type;
        // 验证数据
        $this->getValidate()->scene('to_wxpay')->failException()->check($param);
        // 验证提现金额
        $money = $param['money'];
        $this->checkMoney($money);
        // 验证码
        if ($device_type == 'pc') {
            $code = $param['verify_code'];
            // if ( isset($param['verify_code']) ) {
            $this->checkVerifyCode($code, 'wxpay');
            // }
        }
        // PC端提现到微信生成二维码链接
        if ($device_type == 'pc' || $device_type == 'h5') {
            $order = $this->createWxpayPcOrder($money);
            // 通过公众号获取用户openid
            // if (env('app_debug')) {
            //     $uri = Des::jiami($param['redirect_uri']);
            //     return 'http://seition.com/weauth?ruk=' . $uri . '&order=' . $order->order_no;
            // } else {
            $redirectUri = urlencode($param['redirect_uri'] . "?order=" . $order->order_no);
            $appid       = SystemConfig::get('system.package.payment.wxpay', ['app_id' => ''], request()->mhm_id)['app_id'];
            return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirectUri&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
            // }
        }

        // 非PC端验证 wxpay_openid
        if (!isset($param['wxpay_openid']) || !$param['wxpay_openid']) throw new LogicException("参数错误");
        $openid = strlen($param['wxpay_openid']) > 32 ? Des::jiemi($param['wxpay_openid']) : $param['wxpay_openid'];
        // 提交订单
        return $this->createWxpayOrder($money, $openid);
    }

    // 提交订单 - 提现到微信
    public function createWxpayOrder($money, $openid)
    {
        $mid = request()->mid;
        $this->startTrans();
        try {
            // 订单参数
            $create_data = [
                'order_no'          => app(SnowFlake::class)->createTX(),
                'mhm_id'            => request()->mhm_id,
                'user_id'           => $mid,
                'type'              => 1,
                'status'            => 1,
                'money'             => $money,
                'wxpay_device_type' => request()->device_type,
                'wxpay_openid'      => $openid,
            ];
            // 生成订单
            $order = Encashment::create($create_data);
            if ($order->isEmpty()) throw new LogicException("申请提现失败");
            // 扣除收入
            $this->decreaseIncome($money, '收入提现到微信：' . $money);
            $this->commit();

        } catch (LogicException $e) {
            $this->rollback();
            throw new LogicException($e->getMessage());
        }
        return $order;
    }

    // 提交订单 - 提现到微信
    public function createWxpayPcOrder($money)
    {
        $mid = request()->mid;
        // 订单参数
        $create_data = [
            'order_no'          => app(SnowFlake::class)->createTX(),
            'mhm_id'            => request()->mhm_id,
            'user_id'           => $mid,
            'type'              => 1,
            'status'            => 0,
            'money'             => $money,
            'wxpay_device_type' => request()->device_type,
            'wxpay_openid'      => '',
        ];
        // 生成订单
        $order = Encashment::create($create_data);
        if ($order->isEmpty()) throw new LogicException("申请提现失败");
        return $order;
    }

    // 提现微信PC端检查
    public function toWxpayPcOpenid()
    {
        $code     = Request::get('code/s');
        $order_no = Request::get('order/s');
        // Db::name('test')->save(['msg' => '$code:' . $code . '，order:' . $order_no]);
        $official = SystemConfig::get('system.config.official', ['appid' => '', 'secret' => ''], request()->mhm_id);
        // Db::name('test')->save(['msg' => '$official:' . json_encode($official)]);

        $client = new Client();
        $uri    = 'https://api.weixin.qq.com/sns/oauth2/access_token';
        $param  = [
            'appid'      => $official['appid'],
            'secret'     => $official['secret'],
            'code'       => $code,
            'grant_type' => 'authorization_code'
        ];

        $res      = $client->request('GET', $uri, ['query' => $param]);
        $response = $res->getBody()->getContents();
        // Db::name('test')->save(['msg' => '$response:' . $response]);
        $response = json_decode($response);
        $openid   = $response->openid ?? '';
        // Db::name('test')->save(['msg' => 'openid:' . $openid]);
        if (!$openid) throw new LogicException("提交失败");

        $order = app(Encashment::class)->where('order_no', $order_no)->findOrEmpty();
        if ($order->isEmpty()) throw new LogicException('提现失败');
        $this->startTrans();
        try {
            $order->wxpay_openid = $openid;
            $order->status       = 1;
            if (!$order->save()) throw new LogicException('提现失败');
            // 扣除收入
            $this->decreaseIncome($order->money, '收入提现到微信：' . $order->money, $order->user_id);
            $this->commit();
        } catch (LogicException $e) {
            $this->rollback();
            throw new LogicException($e->getMessage());
        }
    }

    /**
     * 检查PC端微信提现是否提交成功
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 22/03/03
     *
     * @return bool
     */
    public function toWxpayPcCheck(): bool
    {
        $order_no     = Request::get('order_no/s');
        $wxpay_openid = app(Encashment::class)->where('order_no', $order_no)->value('wxpay_openid');
        return (bool)$wxpay_openid;
    }

    /**
     * 检查提现金额是否超支
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-29
     */
    public function checkMoney($money)
    {
        $user_income = $this->userIncome();
        if ($user_income < $money) throw new LogicException('提现金额超支');
    }

    /**
     * 检查提现验证短信
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-29
     */
    public function checkVerifyCode($verify_code, $type)
    {
        // $device_type = request()->device_type;
        // 当前用户手机号
        $phone = request()->user->phone;
        app(Verify::class)->check($phone, $type, $verify_code);

        // 手机端 只有提现到支付宝其他账号需要验证，提现到默认账号只需要输入姓名
        // 其他端 均需要验证
        // $is_app = $device_type == 'android' || $device_type == 'ios';
        // if ( !$is_app || ($is_app && $check_phone != $phone && $check_phone) ) {
        //     // 存在check_phone，即输入的手机号，则验证输入的手机号
        //     $phone = $check_phone ? $check_phone : $phone;
        //     app(Verify::class)->check($phone, $type, $verify_code);
        // }
    }

    /**
     * 收入提现扣除
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date：   2020-06-05
     *
     * @param  [type]                      $money [description]
     * @param string $note
     * @param int    $mid
     * @return Income|array|Model [type]                           [description]
     */
    public function decreaseIncome($money, string $note = '收入提现', int $mid = 0)
    {
        $mid         = $mid ?: request()->mid;
        $user_income = $this->userIncomeInfo($mid);
        // 变更余额
        $user_income->income -= $money;
        if (!$user_income->save()) throw new LogicException('操作失败');
        // 流水记录
        app(IncomeFlow::class)->updateFlow($mid, 8, $money, $user_income->income, 0, 0, $note);
        return $user_income;
    }

}
